#include<iostream>
#include<string>
#include<unistd.h>
#include<pthread.h>
// 条件变量要配合互斥来使用,条件变量本身没有锁
#include<mutex>

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

int tickets = 1000;

void* start_routine(void* args)
{
    std::string name = static_cast<const char*>(args);
    while(true)
    {
        pthread_mutex_lock(&lock);
        pthread_cond_wait(&cond,&lock);
        std::cout << name << "正在抢票： " << tickets << std::endl;
        tickets--;
        pthread_mutex_unlock(&lock);
    }
}
int main()
{
    // 通过条件变量控制线程执行
    // pthread_t t1,t2;
    // pthread_create(&t1,nullptr,start_routine,(void*)"thread 1");
    // pthread_create(&t2,nullptr,start_routine,(void*)"thread 2");
#define num 5
    pthread_t t[num];

    for(int i = 0;i < num; i++)
    {
        // 主线程还没等前一个线程真正开始执行（获取到正确的 namebuffer 内容 ），就已经进入下一次循环，新的 namebuffer 数组内容覆盖了旧的
        // char namebuffer[64];
        // snprintf(namebuffer,sizeof(namebuffer),"thread %d",i+1);
        // pthread_create(&t[i],nullptr,start_routine,(void*)namebuffer);

        //解决方法：
        // 1.堆上创名字，让每个线程分配独立的堆内存
        // 2.结构体保存

        char* name = new char[64];
        snprintf(name,64,"thread %d",i+1);
        pthread_create(&t[i],nullptr,start_routine,(void*)name);
    }

    while(true)
    {
        sleep(1);
        // pthread_cond_signal(&cond);
        pthread_cond_broadcast(&cond); 
        std::cout << "main thread wakeup one thread..." << std::endl;
    }

    // pthread_join(t1,nullptr);
    // pthread_join(t2,nullptr);

    for(int i = 0;i < num; i++)
    {
        pthread_join(t[i],nullptr);
    }

    return 0;
}

////////////////////////////////////////////////接口////////////////////////////////////////////

// int pthread_cond_destroy(pthread_cond_t *cond);
// int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_condattr_t *restrict attr);
// pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

// int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex); 当条件不满足时，让线程等待
// int pthread_cond_broadcast(pthread_cond_t *cond); 唤醒一批线程 broadcast：广播
// int pthread_cond_signal(pthread_cond_t *cond); 唤醒一个线程
